<?php


namespace app\controller\admin;


use app\BaseController;
use app\common\lists\ListsSearchTrait;
use app\common\lists\ListsSortTrait;

use app\controller\interfaces\SearchInterface;
use think\App;
use think\db\Query;
use think\helper\Str;
use think\Model;

abstract class BaseAdminController extends BaseController implements SearchInterface
{
    use ListsSearchTrait;
    use ListsSortTrait;

    protected $page = 1;
    protected $limit = 10;

    // 不显示字段
    protected $visible = [];
    // 是否显示删除数据
    protected $withTrashed = false;

    // 添加时验证规则和验证场景
    protected $validateAdd;
    protected $validateAddScene;

    // 编辑时验证规则和验证场景
    protected $validateEdit;
    protected $validateEditScene;


    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->request = $app->request;
        $this->params = $app->request->param('', '', 'trim');
        if ($this->request->action() == 'getList') {
            $this->initWhere();
            $this->initSort();
        }
    }

    /**
     * 初始化搜索条件
     * @return array
     */
    public function initWhere()
    {
        if (!($this instanceof SearchInterface)) {
            return [];
        }
        $modelName = class_basename($this->getModel()) . '.';
        return [$this->searchWhere, $this->hasWhere] = $this->createWhere($this->setSearch(), $modelName);
    }

    /**
     * 初始化排序条件
     * @return array
     */
    public function initSort()
    {
        if (!($this instanceof SearchInterface)) {
            return [];
        }
        $defaultOrderBy = $this->request->param('order_by', 'id');
        $defaultOrderSort = $this->request->param('sort', 'desc');
        return $this->createSort($this->setSort(), $defaultOrderBy, $defaultOrderSort);
    }

    /**
     * 模型
     * @return Model
     */
    public function getModel(): Model
    {
        return $this->setModel();
    }

    /**
     * 获取列表
     * @return array|\think\Paginator|\think\response\Json
     */
    public function getList()
    {
        try {
            $withModel = $this->setWithModel();
            $hasWhere = $this->hasWhere;
            $list = $this->getModel()
                ->alias(class_basename($this->getModel()))
                ->when($withModel, function (Query $query) use ($withModel, $hasWhere) {
                    $query->with($withModel);
                    foreach ($withModel as $model) {
                        if (isset($hasWhere[$model])) {
                            $query->hasWhere($model, $hasWhere[$model]);
                        }
                    }
                })
                ->when($this->withTrashed, function (Query $query) {
                    $query->withTrashed();
                })
                ->when($this->visible, function (Query $query) {
                    $query->visible($this->visible);
                })
                ->where($this->searchWhere)
                ->order($this->sort)
                ->paginate(['list_rows' => $this->limit, 'page' => $this->page]);
            $bool = $this->existController();
            if (!$bool) {
                return $this->success($list->toArray());
            } else {
                return $list;
            }
        } catch (\Exception $exception) {
            if (!$bool) {
                return $this->error($exception);
            } else {
                throw new \Exception($exception);
            }
        }
    }

    /**
     * 添加，修改
     * @return \think\response\Json
     */
    public function save()
    {
        try {

            $data = $this->request->except(['create_time', 'update_time']);


            $pk = $this->getModel()->getPk();

            if (isset($data[$pk]) && $data[$pk]) {
                if ($this->validateEdit) {
                    if ($this->validateEditScene) {
                        Validate($this->validateEdit)->scene($this->validateEditScene)->check($data);
                    } else {
                        Validate($this->validateEdit)->check($data);
                    }
                }
                $model = $this->getModel()->where($pk, $data[$pk])->find();
                if (!$model) {
                    throw new \Exception('信息不存在');
                }
                $model->save($data);
            } else {
                if ($this->validateAdd) {
                    if ($this->validateAddScene) {
                        Validate($this->validateAdd)->scene($this->validateAddScene)->check($data);
                    } else {
                        Validate($this->validateAdd)->check($data);
                    }
                }
                $model = $this->getModel();
                $model->save($data);
            }
            return $this->success();
        } catch (\Exception $exception) {
            return $this->error($exception);
        }
    }

    /**
     * 删除
     * @return \think\response\Json
     */
    public function del()
    {
        try {
            $id = $this->request->param('id', 0);

            $pk = $this->getModel()->getPk();

            $model = $this->getModel()->where($pk, $id)->find();

            if ($model) {
                $model->delete();
            }
            return $this->success();
        } catch (\Exception $exception) {
            return $this->error($exception);
        }
    }

    /**
     * 修改状态
     * @return \think\response\Json
     */
    public function status()
    {
        try {
            $ids = $this->request->param('id', 0);
            $field = $this->request->param('field', 'status', 'trim');
            $status = $this->request->param('status', 0);

            $pk = $this->getModel()->getPk();
            if (is_array($ids)) {
                foreach ($ids as $id) {
                    $model = $this->getModel()->where($pk, $id)->find();
                    $model->$field = $status;
                    $model->save();
                }
            } else {
                $model = $this->getModel()->where($pk, $ids)->find();
                $model->$field = $status;
                $model->save();
            }
            return $this->success();
        } catch (\Exception $exception) {
            return $this->error($exception);
        }
    }

    /**
     * 获取数组
     * @return array|\think\response\Json
     */
    public function getArr()
    {
        try {
            $list = $this->getModel()->select()->toArray();
            return $this->success($list);
        } catch (\Exception $exception) {
            return $this->error($exception);
        }
    }

    /**
     * 判断控制器在子类是否存在
     * @return bool
     * @throws \Exception
     */
    private function existController()
    {
        try {
            $controller = $this->request->controller();
            $arr = explode('.', $controller);
            array_unshift($arr, 'app\\controller');
            $childClass = implode('\\', $arr) . 'Controller';
            $action = $this->request->action();
            $childMethod = new \ReflectionMethod($childClass, $action);
            $parentMethod = new \ReflectionMethod(__CLASS__, $action);
            return $childMethod->getDeclaringClass()->getName() !== $parentMethod->getDeclaringClass()->getName();
        } catch (\Exception $exception) {
            exit(json_encode(['code' => 0, 'msg' => $exception->getMessage(), 'data' => []]));
        }
    }
}